package org.example.system.controller;


import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.example.system.common.base.BasePageQuery;
import org.example.system.common.enums.OrderStatusEnum;
import org.example.system.common.enums.PayStatusEnum;
import org.example.system.common.enums.PayTypeEnum;
import org.example.system.common.enums.VehicleStatusEnum;
import org.example.system.common.result.Result;
import org.example.system.common.util.DateUtils;
import org.example.system.common.util.OrderSnGenerator;
import org.example.system.config.WechatConfig;
import org.example.system.config.properties.WxPayProperties;
import org.example.system.model.entity.*;
import org.example.system.model.form.OrderForm;
import org.example.system.model.form.RefundForm;
import org.example.system.model.query.OrderQuery;
import org.example.system.model.vo.PageVo;
import org.example.system.service.*;
import org.example.system.service.impl.PaymentStrategyContext;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

@Tag(name = "11.订单管理")
@RestController
@RequestMapping("/api/v1/order")
@RequiredArgsConstructor
@Slf4j
public class BizOrderController {

    @Resource
    private PaymentStrategyContext paymentStrategyContext;

    @Resource
    private BizOrderService orderService;

    @Resource
    private OrderSnGenerator orderSnGenerator;

    @Resource
    private RefundRecordService refundRecordService;

    @Autowired
    private VehicleService vehicleService;

    @Resource
    private ModelMapper modelMapper;


    @Resource
    private WxPayService wxPayService;

    @Resource
    private WxPayProperties wxPayProperties;

    @Resource
    private WechatConfig wechatConfig;

    @Resource
    private BizTradeRecordService tradeRecordService;

    @Resource
    private BizModelService bizModelService;


    @Operation(summary = "新增订单")
    @PostMapping("/add")
    public Result add(@RequestBody OrderForm orderForm) {
        BizOrder order = modelMapper.map(orderForm, BizOrder.class);
        orderService.save(order);
        return Result.success();
    }


    @Operation(summary = "删除订单")
    @DeleteMapping("/delete/{id}")
    public Result delete(@PathVariable Integer id) {
        orderService.removeById(id);
        return Result.success();
    }

    @Operation(summary = "更新订单")
    @PutMapping("/update")
    public Result update(@RequestParam Integer id,@RequestBody OrderForm orderForm) {
        BizOrder order = modelMapper.map(orderForm, BizOrder.class);
        order.setId(id);
        order.setUpdateTime(LocalDateTime.now());
        orderService.updateById(order);
        return Result.success();
    }

    @Operation(summary = "分页查询订单列表")
    @PostMapping("/listPage")
    public Result list(@RequestBody OrderQuery orderQuery) {
        LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();

            /**
         * 条件查询暂弃
         */
        if(StringUtils.hasLength(orderQuery.getOrderNumber())){
            queryWrapper.like(BizOrder::getOutTradeNo,orderQuery.getOrderNumber());
        }
        if(orderQuery.getOrderStatus() != -1){
            queryWrapper.eq(BizOrder::getStatus,orderQuery.getOrderStatus());
        }
        queryWrapper.orderByDesc(BizOrder::getCreateTime);
        int pageNum = orderQuery.getPageNum();
        int pageSize = orderQuery.getPageSize();
        Page<BizOrder> page = new Page<>(pageNum, pageSize);
        orderService.page(page, queryWrapper);
        PageVo pageVo = new PageVo();
        pageVo.setList(page.getRecords());
        pageVo.setTotal(page.getTotal());
        return Result.success(pageVo);
    }
    @Operation(summary = "根据状态分页查询")
    @PostMapping("/list")
    public Result detail(@RequestParam(value = "tenantId") String tenantId,
                        @RequestParam(value = "status", defaultValue = "-1") Integer status,
                         @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
                         @RequestParam(value = "pageSize", defaultValue = "5") int pageSize) {

            LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();

            if (status != -1) {
                queryWrapper.eq(BizOrder::getStatus, status);
            }
            if (tenantId !=null){
                queryWrapper.eq(BizOrder::getTenantId, tenantId);
            }
            queryWrapper.orderByDesc(BizOrder::getCreateTime);

            Page<BizOrder> page = new Page<>(pageNum, pageSize);
            orderService.page(page, queryWrapper);
            PageVo pageVo = new PageVo();
            pageVo.setList(page.getRecords());
            pageVo.setTotal(page.getTotal());
            return Result.success(pageVo);


    }



    @Operation(summary = "根据订单创建时间区间查询")
    @PostMapping("/time")
    public Result time(@RequestParam(value = "startTime", required = false) String startTime,
                       @RequestParam(value = "endTime", required = false) String endTime,
                       @RequestBody BasePageQuery basePageQuery) {
        LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.between(startTime != null && endTime != null, BizOrder::getCreateTime, startTime, endTime);
        queryWrapper.orderByDesc(BizOrder::getCreateTime);
        int pageNum = basePageQuery.getPageNum();
        int pageSize = basePageQuery.getPageSize();
        Page<BizOrder> page = new Page<>(pageNum, pageSize);
        orderService.page(page, queryWrapper);
        PageVo pageVo = new PageVo();
        pageVo.setList(page.getRecords());
        pageVo.setTotal(page.getTotal());
        return Result.success(pageVo);

    }

    @Operation(summary="根据车型模糊查询")
    @GetMapping("/model")
    public Result model(@RequestParam(value = "model", required = false) String model,
                        @RequestBody BasePageQuery basePageQuery) {
        LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(model != null, BizOrder::getModelName, model);
        queryWrapper.orderByDesc(BizOrder::getCreateTime);
        int pageNum = basePageQuery.getPageNum();
        int pageSize = basePageQuery.getPageSize();
        Page<BizOrder> page = new Page<>(pageNum, pageSize);
        orderService.page(page, queryWrapper);
        PageVo pageVo = new PageVo();
        pageVo.setList(page.getRecords());
        pageVo.setTotal(page.getTotal());
        return Result.success(pageVo);
    }

    @Operation(summary = "根据订单号查询")
    @GetMapping("/orderNo")
    public Result orderNo(@RequestParam(value = "outTradeNo", required = false) String outTradeNo){
        BizOrder bizOrder = orderService.getOne(new LambdaQueryWrapper<BizOrder>().eq(BizOrder::getOutTradeNo, outTradeNo));
        return Result.success(bizOrder);
    }

    @Operation(summary = "多条件分页查询")
    @GetMapping("/page")
    public Result page(@RequestBody OrderQuery orderQuery){
        return  null;
    }
//`
//    @PostMapping("/createOrder")
//    public Result createOrder(@RequestBody OrderForm orderForm) {
//        //使用雪花算法生成订单号
//        String orderNumber = orderSnGenerator.makeOrderNumber();
//        BizOrder bizOrder = new BizOrder();
//        bizOrder.setOutTradeNo(orderNumber);
//
//        return null;
//    }


    /**
     * 小程序订单接口清单：
     * 1、生成订单支付（接口：返回结果：小程序调起支付所需参数）
     * 2、根据订单状态（全部订单-1，待支付0，待取车1，用车中2，已还车3，4：已取消）查询订单列表
     * 3、取消订单（已支付成功，在30分钟及以内免责取消，否则不允许取消订单）
     * 4、根据订单号查询订单详情
     * 5、删除订单（待取车、用车中中状态是不允许删除的）
     */

    /**
     * 确认订单
     * @param orderForm 订单对象
     * @return
     */
    @Operation(summary = "确认订单")
    @PostMapping("/create")
    public Result createOrder(@RequestBody OrderForm orderForm) {
        BizOrder newOrder = new BizOrder();
        String outTradeNo = orderSnGenerator.makeOrderNumber();
        newOrder.setOutTradeNo(outTradeNo);
        newOrder.setOpenid(orderForm.getOpenid());
        newOrder.setTenantId(orderForm.getTenantId());
        newOrder.setVehicleId(orderForm.getVehicleId());
        newOrder.setModelId(orderForm.getModelId());
        newOrder.setShopTd(orderForm.getShopId());
        newOrder.setModelName(orderForm.getModelName());
        newOrder.setPickupLocation(orderForm.getPickupLocation());
        newOrder.setDropOffLocation(orderForm.getDropOffLocation());
        newOrder.setPickupTime(orderForm.getPickupTime());
        newOrder.setDropOffTime(orderForm.getDropOffTime());
        newOrder.setTotalFee(orderForm.getTotalFee());
        newOrder.setRemark(orderForm.getRemark());
        newOrder.setStatus(OrderStatusEnum.NO_PAY.getValue());

        orderService.save(newOrder);
        return Result.success(newOrder);
    }


    @Operation(summary = "支付订单[小程序]")
    @GetMapping("/pay")
    public Result payOrder(@RequestParam String orderNumber, HttpServletRequest request) {
        PaymentStrategy paymentStrategy = paymentStrategyContext.getPaymentStrategy(PayTypeEnum.WECHAT_PAY);
        try {
            return paymentStrategy.prePay(orderNumber, request);
        } catch (WxPayException e) {
            return Result.failed(e.getMessage());
        }
    }

    @Operation(summary = "支付结果通知,前端无需调用")
    @PostMapping("/notify")
    public String payNotify(@RequestBody String xmlData) {
        System.out.println(xmlData);
        try {
            // 解析微信支付通知数据
            final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
            log.info("支付结果通知: {}", notifyResult);
            // 校验返回状态码
            if ("SUCCESS".equals(notifyResult.getReturnCode()) && "SUCCESS".equals(notifyResult.getResultCode())) {
                log.info("支付成功，开始处理业务逻辑");

                // 提取支付通知中的数据
                String outTradeNo = notifyResult.getOutTradeNo(); // 商户订单号
                String transactionId = notifyResult.getTransactionId(); // 微信支付订单号
                BigDecimal totalFee = BigDecimal.valueOf(notifyResult.getTotalFee()).divide(BigDecimal.valueOf(100)); // 单位转换为元
                LocalDateTime paymentTime = LocalDateTime.now(); // 支付时间

                // 查询订单信息
                LambdaQueryWrapper<BizOrder> queryCondition = new LambdaQueryWrapper<>();
                queryCondition.eq(BizOrder::getOutTradeNo, outTradeNo);
                BizOrder order = orderService.getOne(queryCondition, true);

                if (order == null) {
                    log.error("支付通知失败：订单号 {} 不存在", outTradeNo);
                    return WxPayNotifyResponse.fail("订单不存在");
                }

                // 更新订单状态为待取车
                order.setStatus(OrderStatusEnum.PAID.getValue());
                orderService.updateById(order);

                // 添加支付交易记录
                BizTradeRecord tradeRecord = new BizTradeRecord();
                tradeRecord.setOrderId(order.getId())
                        .setTenantId(order.getTenantId())
                        .setVehicleId(order.getVehicleId())
                        .setOutTradeNo(outTradeNo)
                        .setTransactionId(transactionId)
                        .setTotalFee(totalFee)
                        .setPaymentTime(paymentTime)
                        .setPaymentType(0) // 0: 微信支付
                        .setTradeStatus(1); // 1: 已支付
                tradeRecordService.save(tradeRecord);

                log.info("支付处理完成：订单号 {}, 微信订单号 {}", outTradeNo, transactionId);
                return WxPayNotifyResponse.success("OK");
            } else {
                log.error("支付失败：{}", notifyResult);
                return WxPayNotifyResponse.fail("支付结果校验失败");
            }
        } catch (WxPayException e) {
            log.error("微信支付通知处理异常: {}", e.getMessage(), e);
            return WxPayNotifyResponse.fail(e.getErrCodeDes());
        } catch (Exception e) {
            log.error("支付通知业务逻辑处理失败: {}", e.getMessage(), e);
            return WxPayNotifyResponse.fail("业务逻辑处理异常");
        }
    }

    @Operation(summary = "申请退款")
    @PostMapping("/applyRefund")
    public Result applyRefund(@RequestBody RefundForm refundForm) {
        String outTradeNo = refundForm.getOutTradeNo();
        LambdaQueryWrapper<BizTradeRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizTradeRecord::getOutTradeNo, outTradeNo);
        BigDecimal totalFee = tradeRecordService.getOne(queryWrapper).getTotalFee();

        // WxJava SDK针对官方请求参数进行二次封装请求参数对象
        WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
        // 商户订单号(out_trade_no)和微信生成的订单号(transaction_id)二选一都可以申请退款
        wxPayRefundRequest.setOutTradeNo(outTradeNo);
        // 使用雪花算法生成【商户系统内部的退款单号】
        String outRefundNo = IdUtil.getSnowflakeNextIdStr();
        wxPayRefundRequest.setOutRefundNo(outRefundNo);
        // 退款金额，单位为分
        Integer refundFee = BaseWxPayRequest.yuanToFen(totalFee.toString());
        wxPayRefundRequest.setTotalFee(refundFee);
        wxPayRefundRequest.setRefundFee(refundFee);
        // 退款资金来源
        wxPayRefundRequest.setRefundAccount(WxPayConstants.RefundAccountSource.UNSETTLED_FUNDS);
        wxPayRefundRequest.setNotifyUrl(wxPayProperties.getRefundUrl());
        wxPayRefundRequest.setRefundDesc(refundForm.getRefundDesc());

        // 创建 RefundRecord 记录
        RefundRecord refundRecord = new RefundRecord()
                .setOutRefundNo(outRefundNo) // 设置商户退款单号
                .setOutTradeNo(refundForm.getOutTradeNo()) // 设置商户订单号
                .setTransactionId(refundForm.getTransactionId() != null ? refundForm.getTransactionId() : "") // 微信支付订单号
                .setTotalFee(totalFee) // 总金额
                .setRefundFee(totalFee) // 退款金额
                .setRefundDesc(refundForm.getRefundDesc()) // 退款原因
                .setRefundStatus(0) // 设置退款状态为退款中
                .setRemark("退款申请已提交");

        // 插入退款记录
        refundRecordService.save(refundRecord);

        try {
            WxPayRefundResult returnMap = wxPayService.refundV2(wxPayRefundRequest);
            if ("SUCCESS".equals(returnMap.getReturnCode()) && "SUCCESS".equals(returnMap.getResultCode())) {
                // 设置微信退款单号并更新退款记录
                refundRecord.setRefundId(returnMap.getRefundId()); // 设置微信退款单号
                refundRecord.setRemark("微信退款已提交，等待回调通知");
                refundRecordService.updateById(refundRecord);

                // 查询订单
                LambdaQueryWrapper<BizOrder> queryCondition = new LambdaQueryWrapper<>();
                queryCondition.eq(BizOrder::getOutTradeNo, refundForm.getOutTradeNo());
                BizOrder order = orderService.getOne(queryCondition, true);

                if (order == null) {
                    return Result.failed("支付通知失败：订单号 " + refundForm.getOutTradeNo() + " 不存在");
                }

                // 获取车辆信息
                Vehicle vehicle = vehicleService.getById(order.getVehicleId());


                // 修改车辆状态
                vehicle.setStatus(0); // 状态改为空闲中
                vehicleService.updateById(vehicle);

                // 更新订单状态为退款中
                orderService.updateOrderState(refundForm.getOutTradeNo(), OrderStatusEnum.REFUND_SUCCESS.getValue());
                return Result.success("退款成功");
            } else {
                // 退款失败，更新退款记录状态
                refundRecord.setRefundStatus(2); // 设置退款状态为退款失败
                refundRecord.setRemark("退款失败：" + returnMap.getErrCodeDes());
                refundRecordService.updateById(refundRecord);
                return Result.failed("退款失败：" + returnMap.getErrCodeDes());
            }
        } catch (WxPayException ex) {
            // 处理异常
            refundRecord.setRefundStatus(2); // 设置退款状态为退款失败
            refundRecord.setRemark("退款异常：" + ex.getErrCodeDes());
            refundRecordService.updateById(refundRecord);
            return Result.failed("退款异常：" + ex.getErrCodeDes());
        }
    }

    @Operation(summary = "退款结果通知,前端无需调用")
    @PostMapping("/refundNotify")
    public String refundNotify(@RequestBody String xmlData) {
        try {
            // 退款回调结果
            WxPayRefundNotifyResult result = wxPayService.parseRefundNotifyResult(xmlData);
            String outRefundNo = result.getReqInfo().getOutRefundNo();
            String transactionId = result.getReqInfo().getTransactionId();

            log.info("回调数据 - outRefundNo: {}, transactionId: {}", outRefundNo, transactionId);

            // 查询对应的退款记录
            RefundRecord refundRecord = refundRecordService.getOne(new QueryWrapper<RefundRecord>().eq("out_refund_no", outRefundNo));
            if (refundRecord == null) {
                log.error("未找到对应的退款记录，outRefundNo: {}", outRefundNo);
                return WxPayNotifyResponse.fail("退款记录不存在");
            }

            // 根据退款状态更新退款记录
            if ("SUCCESS".equals(result.getReqInfo().getRefundStatus())) {
                refundRecord.setRefundStatus(1); // 设置退款状态为成功
                refundRecord.setRefundId(transactionId); // 设置微信退款单号
                refundRecord.setRemark("退款成功");
            } else {
                refundRecord.setRefundStatus(2); // 设置退款状态为失败
                refundRecord.setRemark("退款失败");
            }

            refundRecordService.updateById(refundRecord); // 更新退款记录
            return WxPayNotifyResponse.success("OK");
        } catch (WxPayException e) {
            log.error("退款回调异常,异常原因: {}", e.getMessage());
            return WxPayNotifyResponse.fail(e.getErrCodeDes());
        }
    }


    @Operation(summary = "取消订单[小程序]")
    @GetMapping("/cancel")
    @Transactional
    public Result cancelOrder(@RequestParam String orderNumber) {
        // 查询订单
        LambdaQueryWrapper<BizOrder> queryCondition = new LambdaQueryWrapper<>();
        queryCondition.eq(BizOrder::getOutTradeNo, orderNumber);
        BizOrder order = orderService.getOne(queryCondition, true);

        if (order == null) {
            return Result.failed("订单不存在！");
        }

        // 检查订单状态
        if (order.getStatus() != OrderStatusEnum.NO_PAY.getValue()) {
            return Result.failed("只有待支付状态的订单可以取消！");
        }

        try {
            order.setTotalFee(BigDecimal.valueOf(0));
            order.setStatus(OrderStatusEnum.CANCEL.getValue()); // 设置状态为已取消
            order.setCancelTime(LocalDateTime.now());
            orderService.updateById(order);

            Vehicle vehicle = vehicleService.getById(order.getVehicleId());
            if (vehicle != null) {
                vehicle.setStatus(0); // 设置车辆状态为可用
                vehicleService.updateById(vehicle);
            }
            return Result.success("取消订单成功");
        } catch (Exception e) {
            // 回滚事务
            throw new RuntimeException("取消订单失败", e);
        }
    }

    @Operation(summary = "取车[小程序]")
    @GetMapping("/pickup")
    @Transactional
    public Result pickupCar(@RequestParam String orderNumber) {
        // 查询订单
        LambdaQueryWrapper<BizOrder> queryCondition = new LambdaQueryWrapper<>();
        queryCondition.eq(BizOrder::getOutTradeNo, orderNumber);
        BizOrder order = orderService.getOne(queryCondition, true);

        if (order == null) {
            return Result.failed("订单不存在！");
        }

        // 检查订单状态是否为待取车
        if (order.getStatus() != OrderStatusEnum.PAID.getValue()) {
            return Result.failed("只有待取车状态的订单可以取车！");
        }

        try {
            // 更新订单状态为用车中
            order.setStatus(OrderStatusEnum.USING.getValue());
            orderService.updateById(order);

            // 更新车辆状态为已出租
            Vehicle vehicle = vehicleService.getById(order.getVehicleId());
            if (vehicle != null) {
                vehicle.setStatus(2); // 状态 2: 已出租
                vehicleService.updateById(vehicle);
            }
            return Result.success("取车成功！");
        } catch (Exception e) {
            throw new RuntimeException("取车失败", e);
        }
    }

    @Operation(summary = "还车[小程序]")
    @GetMapping("/return")
    @Transactional
    public Result returnCar(@RequestParam String orderNumber) {
        // 查询订单
        LambdaQueryWrapper<BizOrder> queryCondition = new LambdaQueryWrapper<>();
        queryCondition.eq(BizOrder::getOutTradeNo, orderNumber);
        BizOrder order = orderService.getOne(queryCondition, true);

        if (order == null) {
            return Result.failed("订单不存在！");
        }

        // 检查订单状态是否为用车中
        if (order.getStatus() != OrderStatusEnum.USING.getValue()) {
            return Result.failed("只有用车中状态的订单可以还车！");
        }

        try {
            // 更新订单状态为已还车，设置还车时间
            order.setStatus(OrderStatusEnum.RETURN.getValue());
            order.setDropOffTime(LocalDateTime.now());
            orderService.updateById(order);

            // 更新车辆状态为空闲中
            Vehicle vehicle = vehicleService.getById(order.getVehicleId());
            if (vehicle != null) {
                vehicle.setStatus(0); // 状态 0: 空闲中
                vehicleService.updateById(vehicle);
            }
            return Result.success("还车成功！");
        } catch (Exception e) {
            throw new RuntimeException("还车失败", e);
        }
    }



}
